//===============================================================================
// Microsoft Architecture Strategy Team
// LitwareHR - SaaS Sample Application
//===============================================================================
// Copyright  Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===============================================================================
// The example companies, organizations, products, domain names,
// e-mail addresses, logos, people, places, and events depicted
// herein are fictitious.  No association with any real company,
// organization, product, domain name, email address, logo, person,
// places, or events is intended or should be inferred.
//===============================================================================

using System;
using System.Data;
using System.Data.Common;
using System.Text;

using Microsoft.Practices.EnterpriseLibrary.Data;

using Shp.Runtime.Contract;
using System.Globalization;

namespace Shp.Runtime.Services
{
    internal class DatamodelLogicHelper
    {
        internal class EntityDef
        {
            internal Guid Id;
            internal string Name;
            internal string SharedTableName;
            internal string CustomTableName;
        }

        internal static string GetSharedSchemaSqlCmd(string tenantAlias, string entityDefName)
        {
            // get entity info
            EntityDef def = GetEntityDef(entityDefName);
            EntityField[] fields = DatamodelLogic.GetEntityDefFields(tenantAlias, entityDefName);

            StringBuilder sb = new StringBuilder();
            sb.AppendFormat("INSERT INTO dbo.{0} (", def.SharedTableName);
            sb.Append("[id], [tenantId], ");

            // set colum names
            for (int i = 0; i < fields.Length; i++)
            {
                if (fields[i].IsShared)
                {
                    sb.AppendFormat("[{0}]", fields[i].Name);
                    sb.Append(", ");
                }
            }

            sb.Remove(sb.Length - ", ".Length, ", ".Length);

            sb.Append(") VALUES (");
            sb.Append("@id, @tenantId, ");

            // set values
            for (int i = 0; i < fields.Length; i++)
            {
                if (fields[i].IsShared)
                {
                    sb.AppendFormat("@{0}", fields[i].Name);
                    sb.Append(", ");
                }
            }

            sb.Remove(sb.Length - ", ".Length, ", ".Length);

            sb.Append(") ");

            return sb.ToString();
        }

        internal static string GetCustomShemaSqlCmd(string tenantAlias, string entityDefName)
        {
            EntityDef def = GetEntityDef(entityDefName);
            string s = String.Format(CultureInfo.InvariantCulture, "INSERT INTO dbo.[{0}] (id, instanceId, extensionRef, value) VALUES (@id, @instanceId, @extensionRef, @value)", def.CustomTableName);
            return s;
        }

        internal static DbType GetDbType(string tenantAlias, string entityName, string fieldName)
        {
            EntityField[] fields = DatamodelLogic.GetEntityDefFields(tenantAlias, entityName);

            foreach (EntityField field in fields)
            {
                if (field.Name.CompareTo(fieldName) == 0)
                {
                    switch (field.TypeName)
                    {
                        case "Boolean (Yes | No)":
                            return DbType.Boolean;

                        case "Long text (up to 4000 characters)":
                            return DbType.String;

                        case "Short text (up to 255 characters)":
                            return DbType.String;

                        case "Number":
                            return DbType.Int32;

                        case "Date and time":
                            return DbType.DateTime;
                    }
                }
            }

            throw (new ArgumentException("fieldName is not a valid field name", "fieldName"));
        }

        internal static EntityDef GetEntityDef(string entityDefName)
        {
            EntityDef retVal = null;

            Database db = DatabaseFactory.CreateDatabase(Constants.DB.TenantMetadataStore);
            string sql = "SELECT id, name, schemaTable, valueTable FROM dbo.EntityDef WHERE name = @Name";
            using (DbCommand cmd = db.GetSqlStringCommand(sql))
            {
                db.AddInParameter(cmd, "@Name", DbType.String, entityDefName);

                using (IDataReader rdr = db.ExecuteReader(cmd))
                {
                    if (rdr.Read())
                        retVal = PopulateEntityDefFromIDataReader(rdr);
                }
            }

            return retVal;
        }

        internal static EntityDef PopulateEntityDefFromIDataReader(IDataReader rdr)
        {
            EntityDef retVal = new EntityDef();
            retVal.Id = rdr.GetGuid(0);
            retVal.Name = rdr.GetString(1);
            retVal.SharedTableName = rdr.GetString(2);
            retVal.CustomTableName = rdr.GetString(3);
            return retVal;
        }
    }
}
